define(["jquery", "jquery-ui", "widgets/textStub"], function ($$, $) {
    "use strict";

    var NAME = "panel";
    var BODY = {
        options: {
            name: NAME,
            template: "js/widgets/panel.html",

            content: "textStub",

            loading: "sp-loading",
            loadingDelay: 0 // for testing purposes, in order to emulate network delay
        },

        _create: function () {
            this.element.addClass(this.options.loading)
                .addClass("cp-" + NAME)
                .addClass("insert")
                .addClass("content");
            this.element.data("widget", NAME);

            if (this.options.loadingDelay > 0) {
                var panel = this;
                setTimeout(function () {
                    panel._load();
                }, this.options.loadingDelay);
            } else {
                this._load();
            }
        },

        /**
         * @param options.template should be defined
         *
         * @return html snippet
         * */
        _load: function () {
            var panel = this;
            $.get(this.options.template, function (data) {
                panel.element.removeClass(panel.options.loading);
                panel.element.html(data);

                if (panel.options.loadingDelay > 0) {
                    setTimeout(function () {
                        panel._applyChildrenBinding(panel.element);
                    }, panel.options.loadingDelay);
                } else {
                    panel._applyChildrenBinding(panel.element);
                }
            });
        },

        /**
         * @param el {Element} root dom element
         * @param handler {function (Element, String widgetName)}
         *
         * @return [{css: ..., widget: ...}, ...]
         **/
        _findChildrenForBinding: function (el, handler) {
            var res = [];
            var panel = this;

            $(el).find(".insert").andSelf().each(function (ind, ins) {
                var classes = (ins.className && ins.className.split(" ")) || [];
                for (var i = 0; i < classes.length; i++) {
                    var widgetName = panel.options[classes[i]];
                    if (widgetName) {
                        res.push({
                            css: classes[i],
                            widget: widgetName
                        });

                        if (handler) {
                            handler(ins, widgetName);
                        }
                    }
                }
            });

            return res;
        },

        /*
         *
         *
         **/
        _applyChildrenBinding: function (el) {
            this._findChildrenForBinding(el, function (child, widgetName) {
                if ($.custom[widgetName]) {
                    $.custom[widgetName]({}, child);
                } else {
                    console.log("sp: widget '" + widgetName + "' are not found for '" + NAME + "'");
                }

                //(child, {});
            });
        }
    };

    $.widget("custom." + NAME, BODY);

    return BODY;
});